home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 051-075 / 061 / microemacs / buffer.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  16KB  |  507 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. #if    MEGAMAX & ST520
  13. overlay    "buffer"
  14. #endif
  15.  
  16. /*
  17.  * Attach a buffer to a window. The
  18.  * values of dot and mark come from the buffer
  19.  * if the use count is 0. Otherwise, they come
  20.  * from some other window.
  21.  */
  22. usebuffer(f, n)
  23. {
  24.         register BUFFER *bp;
  25.         register int    s;
  26.         char            bufn[NBUFN];
  27.  
  28.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  29.                 return (s);
  30.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  31.                 return (FALSE);
  32.     return(swbuffer(bp));
  33. }
  34.  
  35. nextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  36.  
  37. {
  38.         register BUFFER *bp;
  39.  
  40.     bp = curbp->b_bufp;
  41.     /* cycle through the buffers to find an eligable one */
  42.     while (bp == NULL || bp->b_flag & BFINVS) {
  43.         if (bp == NULL)
  44.             bp = bheadp;
  45.         else
  46.             bp = bp->b_bufp;
  47.     }
  48.     return(swbuffer(bp));
  49. }
  50.  
  51. swbuffer(bp)    /* make buffer BP current */
  52.  
  53. BUFFER *bp;
  54.  
  55. {
  56.         register WINDOW *wp;
  57.  
  58.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  59.                 curbp->b_dotp  = curwp->w_dotp;
  60.                 curbp->b_doto  = curwp->w_doto;
  61.                 curbp->b_markp = curwp->w_markp;
  62.                 curbp->b_marko = curwp->w_marko;
  63.         }
  64.         curbp = bp;                             /* Switch.              */
  65.     if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  66.         /* read it in and activate it */
  67.         readin(curbp->b_fname, TRUE);
  68.         curbp->b_dotp = lforw(curbp->b_linep);
  69.         curbp->b_doto = 0;
  70.         curbp->b_active = TRUE;
  71.     }
  72.         curwp->w_bufp  = bp;
  73.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  74.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  75.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  76.                 curwp->w_dotp  = bp->b_dotp;
  77.                 curwp->w_doto  = bp->b_doto;
  78.                 curwp->w_markp = bp->b_markp;
  79.                 curwp->w_marko = bp->b_marko;
  80.                 return (TRUE);
  81.         }
  82.         wp = wheadp;                            /* Look for old.        */
  83.         while (wp != NULL) {
  84.                 if (wp!=curwp && wp->w_bufp==bp) {
  85.                         curwp->w_dotp  = wp->w_dotp;
  86.                         curwp->w_doto  = wp->w_doto;
  87.                         curwp->w_markp = wp->w_markp;
  88.                         curwp->w_marko = wp->w_marko;
  89.                         break;
  90.                 }
  91.                 wp = wp->w_wndp;
  92.         }
  93.         return (TRUE);
  94. }
  95.  
  96. /*
  97.  * Dispose of a buffer, by name.
  98.  * Ask for the name. Look it up (don't get too
  99.  * upset if it isn't there at all!). Get quite upset
  100.  * if the buffer is being displayed. Clear the buffer (ask
  101.  * if the buffer has been changed). Then free the header
  102.  * line and the buffer header. Bound to "C-X K".
  103.  */
  104. killbuffer(f, n)
  105.  
  106. {
  107.     register BUFFER *bp;
  108.         register int    s;
  109.         char bufn[NBUFN];
  110.  
  111.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  112.                 return(s);
  113.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  114.                 return (TRUE);
  115.     if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  116.             return (TRUE);        /* by doing nothing.    */
  117.     return(zotbuf(bp));
  118. }
  119.  
  120. zotbuf(bp)    /* kill the buffer pointed to by bp */
  121.  
  122. register BUFFER *bp;
  123.  
  124. {
  125.         register BUFFER *bp1;
  126.         register BUFFER *bp2;
  127.         register int    s;
  128.  
  129.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  130.                 mlwrite("Buffer is being displayed");
  131.                 return (FALSE);
  132.         }
  133.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  134.                 return (s);
  135.         free((char *) bp->b_linep);             /* Release header line. */
  136.         bp1 = NULL;                             /* Find the header.     */
  137.         bp2 = bheadp;
  138.         while (bp2 != bp) {
  139.                 bp1 = bp2;
  140.                 bp2 = bp2->b_bufp;
  141.         }
  142.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  143.         if (bp1 == NULL)                        /* Unlink it.           */
  144.                 bheadp = bp2;
  145.         else
  146.                 bp1->b_bufp = bp2;
  147.         free((char *) bp);                      /* Release buffer block */
  148.         return (TRUE);
  149. }
  150.  
  151. namebuffer(f,n)        /*    Rename the current buffer    */
  152.  
  153. int f, n;        /* default Flag & Numeric arg */
  154.  
  155. {
  156.     register BUFFER *bp;    /* pointer to scan through all buffers */
  157.     char bufn[NBUFN];    /* buffer to hold buffer name */
  158.  
  159.     /* prompt for and get the new buffer name */
  160. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  161.         return(FALSE);
  162.  
  163.     /* and check for duplicates */
  164.     bp = bheadp;
  165.     while (bp != NULL) {
  166.         if (bp != curbp) {
  167.             /* if the names the same */
  168.             if (strcmp(bufn, bp->b_bname) == 0)
  169.                 goto ask;  /* try again */
  170.         }
  171.         bp = bp->b_bufp;    /* onward */
  172.     }
  173.  
  174.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  175.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  176.     mlerase();
  177.     return(TRUE);
  178. }
  179.  
  180. /*
  181.  * List all of the active
  182.  * buffers. First update the special
  183.  * buffer that holds the list. Next make
  184.  * sure at least 1 window is displaying the
  185.  * buffer list, splitting the screen if this
  186.  * is what it takes. Lastly, repaint all of
  187.  * the windows that are displaying the
  188.  * list. Bound to "C-X C-B".
  189.  */
  190. listbuffers(f, n)
  191. {
  192.         register WINDOW *wp;
  193.         register BUFFER *bp;
  194.         register int    s;
  195.  
  196.         if ((s=makelist()) != TRUE)
  197.                 return (s);
  198.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  199.                 if ((wp=wpopup()) == NULL)
  200.                         return (FALSE);
  201.                 bp = wp->w_bufp;
  202.                 if (--bp->b_nwnd == 0) {
  203.                         bp->b_dotp  = wp->w_dotp;
  204.                         bp->b_doto  = wp->w_doto;
  205.                         bp->b_markp = wp->w_markp;
  206.                         bp->b_marko = wp->w_marko;
  207.                 }
  208.                 wp->w_bufp  = blistp;
  209.                 ++blistp->b_nwnd;
  210.         }
  211.         wp = wheadp;
  212.         while (wp != NULL) {
  213.                 if (wp->w_bufp == blistp) {
  214.                         wp->w_linep = lforw(blistp->b_linep);
  215.                         wp->w_dotp  = lforw(blistp->b_linep);
  216.                         wp->w_doto  = 0;
  217.                         wp->w_markp = NULL;
  218.                         wp->w_marko = 0;
  219.                         wp->w_flag |= WFMODE|WFHARD;
  220.                 }
  221.                 wp = wp->w_wndp;
  222.         }
  223.         return (TRUE);
  224. }
  225.  
  226. /*
  227.  * This routine rebuilds the
  228.  * text in the special secret buffer
  229.  * that holds the buffer list. It is called
  230.  * by the list buffers command. Return TRUE
  231.  * if everything works. Return FALSE if there
  232.  * is an error (if there is no memory).
  233.  */
  234. makelist()
  235. {
  236.         register char   *cp1;
  237.         register char   *cp2;
  238.         register int    c;
  239.         register BUFFER *bp;
  240.         register LINE   *lp;
  241.         register int    s;
  242.     register int    i;
  243.         long    nbytes;        /* # of bytes in current buffer */
  244.         char            b[7+1];
  245.         char            line[128];
  246.  
  247.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  248.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  249.                 return (s);
  250.         strcpy(blistp->b_fname, "");
  251.         if (addline("AC MODES       Size Buffer        File") == FALSE
  252.         ||  addline("-- -----       ---- ------        ----") == FALSE)
  253.                 return (FALSE);
  254.         bp = bheadp;                            /* For all buffers      */
  255.  
  256.     /* build line to report global mode settings */
  257.     cp1 = &line[0];
  258.     *cp1++ = ' ';
  259.     *cp1++ = ' ';
  260.     *cp1++ = ' ';
  261.  
  262.     /* output the mode codes */
  263.     for (i = 0; i < NUMMODES; i++)
  264.         if (gmode & (1 << i))
  265.             *cp1++ = modecode[i];
  266.         else
  267.             *cp1++ = '.';
  268.     strcpy(cp1, "         Global Modes");
  269.     if (addline(line) == FALSE)
  270.         return(FALSE);
  271.  
  272.     /* output the list of buffers */
  273.         while (bp != NULL) {
  274.                 if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
  275.                         bp = bp->b_bufp;
  276.                         continue;
  277.                 }
  278.                 cp1 = &line[0];                 /* Start at left edge   */
  279.  
  280.         /* output status of ACTIVE flag (has the file been read in? */
  281.                 if (bp->b_active == TRUE)    /* "@" if activated       */
  282.                         *cp1++ = '@';
  283.                 else
  284.                         *cp1++ = ' ';
  285.  
  286.         /* output status of changed flag */
  287.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  288.                         *cp1++ = '*';
  289.                 else
  290.                         *cp1++ = ' ';
  291.                 *cp1++ = ' ';                   /* Gap.                 */
  292.  
  293.         /* output the mode codes */
  294.         for (i = 0; i < NUMMODES; i++) {
  295.             if (bp->b_mode & (1 << i))
  296.                 *cp1++ = modecode[i];
  297.             else
  298.                 *cp1++ = '.';
  299.         }
  300.                 *cp1++ = ' ';                   /* Gap.                 */
  301.                 nbytes = 0L;                    /* Count bytes in buf.  */
  302.                 lp = lforw(bp->b_linep);
  303.                 while (lp != bp->b_linep) {
  304.                         nbytes += (long)llength(lp)+1L;
  305.                         lp = lforw(lp);
  306.                 }
  307.                 ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  308.                 cp2 = &b[0];
  309.                 while ((c = *cp2++) != 0)
  310.                         *cp1++ = c;
  311.                 *cp1++ = ' ';                   /* Gap.                 */
  312.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  313.                 while ((c = *cp2++) != 0)
  314.                         *cp1++ = c;
  315.                 cp2 = &bp->b_fname[0];          /* File name            */
  316.                 if (*cp2 != 0) {
  317.                         while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  318.                                 *cp1++ = ' ';
  319.                         while ((c = *cp2++) != 0) {
  320.                                 if (cp1 < &line[128-1])
  321.                                         *cp1++ = c;
  322.                         }
  323.                 }
  324.                 *cp1 = 0;                       /* Add to the buffer.   */
  325.                 if (addline(line) == FALSE)
  326.                         return (FALSE);
  327.                 bp = bp->b_bufp;
  328.         }
  329.         return (TRUE);                          /* All done             */
  330. }
  331.  
  332. ltoa(buf, width, num)
  333.  
  334. char   buf[];
  335. int    width;
  336. long   num;
  337.  
  338. {
  339.         buf[width] = 0;                         /* End of string.       */
  340.         while (num >= 10) {                     /* Conditional digits.  */
  341.                 buf[--width] = (int)(num%10L) + '0';
  342.                 num /= 10L;
  343.         }
  344.         buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  345.         while (width != 0)                      /* Pad with blanks.     */
  346.                 buf[--width] = ' ';
  347. }
  348.  
  349. /*
  350.  * The argument "text" points to
  351.  * a string. Append this line to the
  352.  * buffer list buffer. Handcraft the EOL
  353.  * on the end. Return TRUE if it worked and
  354.  * FALSE if you ran out of room.
  355.  */
  356. addline(text)
  357. char    *text;
  358. {
  359.         register LINE   *lp;
  360.         register int    i;
  361.         register int    ntext;
  362.  
  363.         ntext = strlen(text);
  364.         if ((lp=lalloc(ntext)) == NULL)
  365.                 return (FALSE);
  366.         for (i=0; i<ntext; ++i)
  367.                 lputc(lp, i, text[i]);
  368.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  369.         lp->l_bp = blistp->b_linep->l_bp;
  370.         blistp->b_linep->l_bp = lp;
  371.         lp->l_fp = blistp->b_linep;
  372.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  373.                 blistp->b_dotp = lp;            /* move it to new line  */
  374.         return (TRUE);
  375. }
  376.  
  377. /*
  378.  * Look through the list of
  379.  * buffers. Return TRUE if there
  380.  * are any changed buffers. Buffers
  381.  * that hold magic internal stuff are
  382.  * not considered; who cares if the
  383.  * list of buffer names is hacked.
  384.  * Return FALSE if no buffers
  385.  * have been changed.
  386.  */
  387. anycb()
  388. {
  389.         register BUFFER *bp;
  390.  
  391.         bp = bheadp;
  392.         while (bp != NULL) {
  393.                 if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  394.                         return (TRUE);
  395.                 bp = bp->b_bufp;
  396.         }
  397.         return (FALSE);
  398. }
  399.  
  400. /*
  401.  * Find a buffer, by name. Return a pointer
  402.  * to the BUFFER structure associated with it.
  403.  * If the buffer is not found
  404.  * and the "cflag" is TRUE, create it. The "bflag" is
  405.  * the settings for the flags in in buffer.
  406.  */
  407. BUFFER  *
  408. bfind(bname, cflag, bflag)
  409. register char   *bname;
  410. {
  411.         register BUFFER *bp;
  412.     register BUFFER *sb;    /* buffer to insert after */
  413.         register LINE   *lp;
  414.     char *malloc();
  415.  
  416.         bp = bheadp;
  417.         while (bp != NULL) {
  418.                 if (strcmp(bname, bp->b_bname) == 0)
  419.                         return (bp);
  420.                 bp = bp->b_bufp;
  421.         }
  422.         if (cflag != FALSE) {
  423.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  424.                         return (NULL);
  425.                 if ((lp=lalloc(0)) == NULL) {
  426.                         free((char *) bp);
  427.                         return (NULL);
  428.                 }
  429.         /* find the place in the list to insert this buffer */
  430.         if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  431.             /* insert at the beginning */
  432.                     bp->b_bufp = bheadp;
  433.                     bheadp = bp;
  434.             } else {
  435.             sb = bheadp;
  436.             while (sb->b_bufp != NULL) {
  437.                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  438.                     break;
  439.                 sb = sb->b_bufp;
  440.             }
  441.  
  442.             /* and insert it */
  443.                    bp->b_bufp = sb->b_bufp;
  444.                 sb->b_bufp = bp;
  445.                }
  446.  
  447.         /* and set up the other buffer fields */
  448.         bp->b_active = TRUE;
  449.                 bp->b_dotp  = lp;
  450.                 bp->b_doto  = 0;
  451.                 bp->b_markp = NULL;
  452.                 bp->b_marko = 0;
  453.                 bp->b_flag  = bflag;
  454.         bp->b_mode  = gmode;
  455.                 bp->b_nwnd  = 0;
  456.                 bp->b_linep = lp;
  457.                 strcpy(bp->b_fname, "");
  458.                 strcpy(bp->b_bname, bname);
  459. #if    CRYPT
  460.         bp->b_key[0] = 0;
  461. #endif
  462.                 lp->l_fp = lp;
  463.                 lp->l_bp = lp;
  464.         }
  465.         return (bp);
  466. }
  467.  
  468. /*
  469.  * This routine blows away all of the text
  470.  * in a buffer. If the buffer is marked as changed
  471.  * then we ask if it is ok to blow it away; this is
  472.  * to save the user the grief of losing text. The
  473.  * window chain is nearly always wrong if this gets
  474.  * called; the caller must arrange for the updates
  475.  * that are required. Return TRUE if everything
  476.  * looks good.
  477.  */
  478. bclear(bp)
  479. register BUFFER *bp;
  480. {
  481.         register LINE   *lp;
  482.         register int    s;
  483.  
  484.         if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  485.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  486.         && (s=mlyesno("Discard changes")) != TRUE)
  487.                 return (s);
  488.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  489.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  490.                 lfree(lp);
  491.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  492.         bp->b_doto  = 0;
  493.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  494.         bp->b_marko = 0;
  495.         return (TRUE);
  496. }
  497.  
  498. unmark(f, n)    /* unmark the current buffers change flag */
  499.  
  500. int f, n;    /* unused command arguments */
  501.  
  502. {
  503.     curbp->b_flag &= ~BFCHG;
  504.     curwp->w_flag |= WFMODE;
  505.     return(TRUE);
  506. }
  507.